package com.buaa.demo.Controller;

import com.buaa.demo.Entity.Choice;
import com.buaa.demo.Entity.Question;
import com.buaa.demo.Entity.Questionnaire;
import com.buaa.demo.Entity.ShortAnswer;
import com.buaa.demo.Entity.Submission;
import com.buaa.demo.Entity.User;
import com.buaa.demo.Service.QuestionService;
import com.buaa.demo.Service.SubmissionService;
import com.buaa.demo.Service.UserService;

import org.hibernate.annotations.SourceType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.relational.core.sql.In;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@CrossOrigin
@RestController
public class QuestionnaireController {

    @Autowired
    public QuestionService questionService;

    @Autowired
    public UserService userService;

    @Autowired
    public SubmissionService submissionService;

    @PostMapping("/createQuestionnaire")
    public Map<String, Object> createQuestionnaire(@RequestBody Map<String, Object> remap){
        System.out.println();
        System.out.println();
        System.out.println("*******************       create new qn        *******************");
        String qn_state = (String)remap.get("state");
        String create_time = (String)remap.get("cur_time");

        int max_commit = 65535;
        if(remap.get("max_commit") != null){
            max_commit = (Integer)remap.get("max_commit");
        }
        String publish_time = null;
        if(qn_state.equals("saved")){
            publish_time = null;
        } else if(qn_state.equals("published")){
            publish_time = create_time;
        }
        Questionnaire qn = new Questionnaire((String)remap.get("title"), Integer.parseInt((String)remap.get("u_id")), (String)remap.get("description"), (String)remap.get("start_time"), (String)remap.get("end_time"), (String)remap.get("state"), (Boolean) remap.get("needed_login"), create_time, publish_time, (String)remap.get("qn_password"), (String)remap.get("qn_type"), max_commit);
        Map<String, Object> resMap = new HashMap<>();
        try{
            String cur_time = (String)remap.get("cur_time");
            questionService.addQuestionnaire(qn);
            checkState(cur_time, qn);
            System.out.println(qn);
            List<Map<String, Object>> questionList = (ArrayList<Map<String, Object>>)remap.get("questions");
            for (Map<String, Object> question : questionList) {
                String type = (String) question.get("type");
                int min_num = 1;
                int max_num = 1;
                if(type.equals("multi_choice")){
                    min_num = Integer.parseInt((String)question.get("min_num"));
                    max_num = Integer.parseInt((String)question.get("max_num"));
                }
                Question q = new Question(qn.qn_id, type, (String) question.get("title"), (Boolean)question.get("permit_null"), (String)question.get("description"), min_num, max_num, max_commit);
                questionService.addQuestion(q);
                System.out.println(q);
                int q_id = q.q_id;
                if(type.equals("single_choice") || type.equals("multi_choice")){
                    List<Map<String, Object>> choices = (ArrayList<Map<String, Object>>)question.get("choices");
                    System.out.println("choices");
                    System.out.println(choices);
                    for(Map<String, Object> choice : choices){
                        System.out.println("choice max_commit : " + String.valueOf((Integer)choice.get("max_commit")));
                        int mmax_commit = 65535;
                        if(choice.get("max_commit") != null){
                            mmax_commit = (Integer)choice.get("max_commit");
                        }
                        Choice c = new Choice(q_id, (String)choice.get("head"), (String)choice.get("description"), mmax_commit);
                        questionService.addChoice(c);
                    }
                }
            }

        } catch(Exception e){
            e.printStackTrace();
            resMap.put("res", false);
            resMap.put("message", "新建问卷错误");
            return resMap;
        }
        System.out.println("finished");
        System.out.println();
        System.out.println();
        resMap.put("res", true);
        resMap.put("message", "问卷创建成功");
        resMap.put("questionnaire", qn);
        return resMap;
    }

    @PostMapping("/getQuestionnaireByQnId")
    public Map<String, Object> getQuestionnaireByQnId(@RequestBody Map<String, Object> remap){
        System.out.println();
        System.out.println();
        System.out.println("getQuestionnaireByQnId");
        int qn_id = Integer.parseInt((String)remap.get("qn_id"));
        System.out.println("qn_id ： " + String.valueOf(qn_id));
        String cur_time = (String)remap.get("cur_time");
        System.out.println("cur_time : " + cur_time );
        try{
            Map<String, Object> resMap = getQuestionnaire(qn_id, cur_time);
            resMap.put("res", true);
            resMap.put("message", "成功获取问卷信息");
            System.out.println((Questionnaire)resMap.get("questionnaire"));
            System.out.println();
            System.out.println("finished");
            System.out.println();
            return resMap;
        } catch (Exception e){
            e.printStackTrace();
            Map<String, Object> falseMap = new HashMap<>();
            falseMap.put("res", false);
            falseMap.put("message", "获取数据刨除异常，请联系管理员");
            return falseMap;
        }
    }

    @PostMapping("/getQuestionnaireByUId")
    public Map<String, Object> getQuestionnaireByUId(@RequestBody Map<String, Object> remap){
        System.out.println();
        System.out.println();
        System.out.println("getQuestionnaireByUId");
        int u_id = Integer.parseInt((String)remap.get("u_id"));
        System.out.println("u_id ： " + String.valueOf(u_id));
        String cur_time = (String) remap.get("cur_time");
        System.out.println("cur_time : " + cur_time );
        List<Questionnaire> qnList = questionService.getQuestionnaireByUId(u_id);
        for(Questionnaire qn : qnList){
            checkState(cur_time, qn);
        }
        System.out.println("finished");
        System.out.println();
        System.out.println();
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("res", true);
        resMap.put("message", "用户发起的问卷");
        resMap.put("questionnaire_list", qnList);
        return resMap;

    }

    @PostMapping("/submitAnswer")
    public Map<String, Object> submitAnswer(@RequestBody Map<String, Object> remap){
        System.out.println();
        System.out.println();
        System.out.println("****************        submit answer         *****************");
        System.out.println();
        System.out.println();
        int qn_id = Integer.parseInt((String) remap.get("qn_id"));
        int u_id = 0;
        String submit_ip = null;
        String submit_address = null;
        String user_name = null;
        if(remap.get("u_id") == null){
            User tempU = new User();
            userService.registerNewUser(tempU);
            u_id = tempU.u_id;
        } else{
            u_id = (Integer)remap.get("u_id");
        }
        if(remap.get("submit_ip") != null){
            submit_ip = (String) remap.get("submit");
        }
        if(remap.get("submit_address") != null){
            submit_address = (String) remap.get("submit_address");
        }
        if(remap.get("user_name") != null){
            user_name = (String) remap.get("user_name");
        }
        System.out.println("qn_id   :   " + String.valueOf(qn_id));
        System.out.println("u   :   " + String.valueOf(u_id));
        System.out.println("cur_time   :   " + (String) remap.get("cur_time"));
        Questionnaire qn = questionService.getQuestionnaireById(qn_id);
        Map<String, Object> resMap = null;
        if(qn.max_commit == qn.qn_count){
            resMap = new HashMap<>();
            resMap.put("res", false);
            resMap.put("message", "问卷填写人数已到达上限");
            return resMap;
        } else if(qn.qn_state.equals("saved")){
            resMap = new HashMap<>();
            resMap.put("res", false);
            resMap.put("message", "问卷暂停中，无法提交，请联系发起人解决");
            return resMap;
        } else if(((String) remap.get("cur_time")).compareTo(qn.end_time) > 0){
            questionService.changeState(qn.qn_id, "finished");
            resMap = new HashMap<>();
            resMap.put("res", false);
            resMap.put("message", "问卷已关闭");
            return resMap;
        }
        List<Map<String, Object>> questionMap = (ArrayList<Map<String, Object>>)remap.get("questionMap");
        try{
            for(Map<String, Object> map : questionMap){
                System.out.println("208 : q_id :" + String.valueOf((Integer) map.get("q_id")));
                int q_id = (Integer) map.get("q_id");
                String type = (String) map.get("type");
                if(type.equals("single_choice")){
                    int c_id = (Integer) map.get("c_id");
                    Choice c = questionService.getChoiceByCId(c_id);
                    if(c.c_count == c.max_commit){
                        resMap = new HashMap<>();
                        resMap.put("res", false);
                        resMap.put("message", "选项填写人数已到达上限");
                        return resMap;
                    }
                } else if(type.equals("multi_choice")) {
                    List<Integer> c_idList = (ArrayList<Integer>) map.get("c_id");
                    for(Integer s : c_idList){
                        int c_id = s.intValue();
                        Choice c = questionService.getChoiceByCId(c_id);
                        if(c.c_count == c.max_commit){
                            resMap = new HashMap<>();
                            resMap.put("res", false);
                            resMap.put("message", "选项填写人数已到达上限");
                            return resMap;
                        }
                    }
                }
            }
            for(Map<String, Object> map : questionMap){
                int q_id = (Integer) map.get("q_id");
                String type = (String) map.get("type");
                questionService.submitQuestion(q_id);
                if(type.equals("single_choice")){
                    int c_id = (Integer) map.get("c_id");
                    questionService.submitChoice(c_id);
                    submissionService.submit(new Submission(u_id, user_name, submit_ip, submit_address, qn_id, q_id, c_id));
                } else if(type.equals("multi_choice")) {
                    List<Integer> c_idList = (ArrayList<Integer>) map.get("c_id");
                    for(Integer s : c_idList){
                        int c_id = s.intValue();
                        questionService.submitChoice(c_id);
                        submissionService.submit(new Submission(u_id, user_name, submit_ip, submit_address, qn_id, q_id, c_id));
                    }
                } else if(type.equals("short_answer") || type.equals("score") || type.equals("location")){
                    questionService.submitShortAnswer(new ShortAnswer(q_id, (String) map.get("answer")));
                    submissionService.submit(new Submission(u_id, user_name, submit_ip, submit_address, qn_id, q_id, (String) map.get("answer")));
                } else{
                    throw new Exception("不被识别的题型");
                }
            }
            resMap = getQuestionnaire(qn_id, (String) remap.get("cur_time"));
        } catch(Exception e){
            e.printStackTrace();
            resMap = new HashMap<>();
            resMap.put("res", false);
            resMap.put("message", "数据提交失败，请重试");
            return resMap;
        }
        System.out.println("finished");
        System.out.println();
        System.out.println();
        resMap.put("res", true);
        resMap.put("message", "问卷提交成功");
        questionService.submitQuestionnaire(qn.qn_id);
        return resMap;
    }

    @PostMapping("/deleteQuestionnaire")
    public Map<String, Object> deleteQuestionnaire(@RequestBody Map<String, String>map){
        int qn_id = Integer.parseInt(map.get("qn_id"));
        Map<String, Object> resMap = new HashMap<>();
        try{
            List<Question> questionList = (ArrayList<Question>)questionService.getQuestionByQnId(qn_id);
            for(Question q : questionList){
                questionService.deleteQuestion(q.q_id);
            }
            questionService.deleteQuestionnaire(qn_id);
        } catch(Exception e){
            e.printStackTrace();
            resMap.put("res", false);
            resMap.put("message", "删除失败，抛出异常");
            return resMap;
        }
        resMap.put("res", true);
        resMap.put("message", "删除成功");
        return resMap;

    }

    @PostMapping("/changeState")
    public Map<String, Object> changeState(@RequestBody Map<String, String> remap){
        StaticPrint.printArgs("change state", remap);
        int qn_id = Integer.parseInt(remap.get("qn_id"));
        String new_state = remap.get("new_state");
        String cur_time = remap.get("cur_time");
        Map<String, Object> resMap = new HashMap<>();
        try{
            questionService.changeState(qn_id, new_state);
            if(new_state.equals("published")){
                questionService.adjustPublishTime(qn_id, cur_time);
            }
        } catch(Exception e){
            e.printStackTrace();
            resMap.put("res", false);
            resMap.put("message", "更改状态时抛出异常");
            return resMap;
        }
        resMap.put("res", true);
        resMap.put("message", "用户发起的问卷");
        return resMap;
    }

    @PostMapping("/getSubmission")
    public Map<String, Object> getSubmission(@RequestBody Map<String, Object> remap){
        Map<String, Object> resMap = new HashMap<>();
        int qn_id = (Integer) remap.get("qn_id");
        List<Object> submission = new ArrayList<>();
        try{
            List<Integer> uidList = submissionService.getUIds(qn_id);
            for(int u_id : uidList) {
                Map<String, Object> temp = new HashMap<>();
                List<Map<String, Object>> questions = new ArrayList<>();
                List<Submission> subList = submissionService.getSubmissions(qn_id, u_id);
                List<Integer> q_idList = submissionService.getQIds(qn_id, u_id);
                Submission sub = subList.get(0);
                temp.put("u_id", sub.u_id);
                temp.put("username", sub.user_name);
                temp.put("submit_ip", sub.ip);
                temp.put("submit_address", sub.address);
                for(int q_id : q_idList){
                    Map<String, Object> map = new HashMap<>();
                    Question q = questionService.getQuestionByQId(q_id);
                    map.put("q_id", q_id);
                    map.put("type", q.type);
                    map.put("title", q.title);
                    map.put("description", q.description);
                    List<String> ansList = new ArrayList<>();
                    if(q.type.equals("single_choice") || q.type.equals("multi_choice")){
                        List<Integer> c_idList = submissionService.getCIds(qn_id, u_id, q_id);
                        for(int c_id : c_idList){
                            Choice c = questionService.getChoiceByCId(c_id);
                            ansList.add(c.head + "." + c.description);
                        }

                    } else if(q.type.equals("short_answer") || q.type.equals("score")){
                        ansList.add(submissionService.getAnswers(qn_id, u_id, q_id));
                    }
                    map.put("answer", ansList);
                    questions.add(map);
                }
                temp.put("question", questions);
                submission.add(temp);
            }
        } catch(Exception e){
            e.printStackTrace();
            resMap.put("res", false);
            resMap.put("message","获取数据出错，请与管理员联系。");
            return resMap;
        }
        resMap.put("res", true);
        resMap.put("message", "hhh");
        resMap.put("submission", submission);
        return resMap;
    }

    @PostMapping("/copyQuestionnaire")
    public Map<String, Object> copyQn(@RequestBody Map<String, Object> remap){
        System.out.println();
        System.out.println();
        System.out.println("******************   copy questionnaire   *********************");
        int qn_id = (Integer) remap.get("qn_id");
        System.out.println("qn_id :" + String.valueOf(qn_id));
        String cur_time = (String) remap.get("cur_time");
        Map<String, Object> resMap = null;
        try{
            Questionnaire qn = questionService.getQuestionnaireById(qn_id);
            List<Question> qList = questionService.getQuestionByQnId(qn.qn_id);
            Questionnaire qn_new = new Questionnaire(qn.title + "的副本", qn.user_id, qn.description, qn.start_time, qn.end_time, qn.qn_state, qn.needed_login, qn.create_time, qn.publish_time, qn.qn_password, qn.qn_type, qn.max_commit);
            questionService.addQuestionnaire(qn_new);
            for(Question q : qList){
                Question q_new = new Question(qn_new.qn_id, q.type, q.title, q.permit_null, q.description, q.min_num, q.max_num, q.max_commit);
                questionService.addQuestion(q_new);
                List<Choice> cList = questionService.getChoiceByQId(q.q_id);
                for(Choice c : cList){
                    Choice c_new = new Choice(q_new.q_id, c.head, c.description, c.max_commit);
                    questionService.addChoice(c_new);
                }
            }
            resMap = getQuestionnaire(qn_new.qn_id, cur_time);
            resMap.put("res", true);
            resMap.put("message", "成功返回");
            System.out.println("finished");
            System.out.println();
            System.out.println();
            return resMap;
        } catch(Exception e){
            e.printStackTrace();
            resMap = new HashMap<>();
            resMap.put("res", false);
            resMap.put("message", "抛出异常");
            return resMap;
        }

    }


    public Map<String, Object> getQuestionnaire(int qn_id, String cur_time) throws Exception{
        Questionnaire qn = questionService.getQuestionnaireById(qn_id);
        checkState(cur_time, qn);
        List<Question> questionList = (ArrayList<Question>)questionService.getQuestionByQnId(qn_id);
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("questionnaire", qn);
        List<Map<String, Object>> qList = new ArrayList<>();
        for(Question q : questionList){
            List<Choice> choiceList = (ArrayList<Choice>)questionService.getChoiceByQId(q.q_id);
            Map<String, Object> questionMap = new HashMap<>();
            questionMap.put("q_id", new Integer(q.q_id));
            questionMap.put("qn_id", new Integer(q.qn_id));
            questionMap.put("title", q.title);
            questionMap.put("type", q.type);
            questionMap.put("q_count", q.q_count);
            questionMap.put("description", q.description);
            questionMap.put("permit_null", q.permit_null);
            questionMap.put("max_num", q.max_num);
            questionMap.put("min_num", q.min_num);
            if(q.type.equals("single_choice") || q.type.equals("multi_choice")){
                questionMap.put("choices", choiceList);
            } else if(q.type.equals("short_answer") || q.type.equals("score") || q.type.equals("location")){
                questionMap.put("answer", questionService.getShortAnswerByQId(q.q_id));
            }
            qList.add(questionMap);
        }
        resMap.put("question_list", qList);
        return resMap;
    }

    public void checkState(String cur_time, Questionnaire qn){
        if((!qn.qn_state.equals("saved")) && (!qn.qn_state.equals("deleted"))) {
            if (cur_time.compareTo(qn.start_time) < 0) {
                qn.qn_state = "published";
            } else if (cur_time.compareTo(qn.end_time) > 0) {
                qn.qn_state = "finished";
            } else {
                qn.qn_state = "started";
            }
            questionService.changeState(qn.qn_id, qn.qn_state);
        }

    }


//    public QuestionType getType(String type){
//        if(type.equals("single_choice")){
//            return QuestionType.single_choice;
//        } else if(type.equals("multi_choice")){
//            return QuestionType.multi_choices;
//        } else if(type.equals("judge")) {
//            return QuestionType.judge;
//        } else{
//            return QuestionType.short_answer;
//        }
//    }

//    public QuestionnaireState getState(String state){
//        if(state.equals("editing")){
//            return QuestionnaireState.editing;
//        } else if(state.equals("running")){
//            return QuestionnaireState.running;
//        } else if(state.equals("waiting")) {
//            return QuestionnaireState.waiting;
//        } else if(state.equals("paused")) {
//            return QuestionnaireState.paused;
//        } else{
//            return QuestionnaireState.closed;
//        }
//    }

}
